﻿using EasyXaf.EntityDesigner.BusinessObjects.Entities;
using EasyXaf.EntityDesigner.BusinessObjects.Entities.EntityProperties;
using EasyXaf.EntityDesigner.Commands.PropertyTypeBuilders;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;

namespace EasyXaf.EntityDesigner.Commands;

public class CreateEntityPropertyCommand : ICommand
{
    private static readonly ConcurrentBag<IPropertyTypeBuilder> PropertyTypeBuilders = [];

    public void CreateEntityProperty(string command, Entity entity)
    {
        var matches = Regex.Matches(command.Trim(), @"(?<=\s|^).*?(?=\s|$)").Cast<Match>();

        var propertyName = matches.FirstOrDefault()?.Value;
        if (string.IsNullOrWhiteSpace(propertyName))
        {
            throw new CommandException(command, "属性名称不能为空");
        }

        var caption = matches.Skip(2).FirstOrDefault()?.Value;
        if (matches.Skip(1).FirstOrDefault()?.Value?.StartsWith('-') == true)
        {
            caption = matches.Skip(1).First().Value[1..];
            matches = matches.Take(1).ToList();
        }

        var property = new EntityProperty(entity.Session)
        {
            Name = propertyName,
            Caption = caption,
            Order = entity.Properties.Count + 1,
            Entity = entity
        };

        if (PropertyTypeBuilders.IsEmpty)
        {
            var builderTypes = typeof(Entity).Assembly.GetTypes()
                .Where(type => typeof(IPropertyTypeBuilder).IsAssignableFrom(type) && !type.IsAbstract)
                .ToList();
            foreach (var type in builderTypes)
            {
                PropertyTypeBuilders.Add((IPropertyTypeBuilder)Activator.CreateInstance(type));
            }
        }

        var propertyType = matches.Skip(1).FirstOrDefault()?.Value;
        if (string.IsNullOrWhiteSpace(propertyType))
        {
            propertyType = "string";
        }
        else if (int.TryParse(propertyType, out var stringLength))
        {
            propertyType = $"string({stringLength})";
        }
        else if (propertyType.Split(',').Length == 2)
        {
            if (int.TryParse(propertyType.Split(',')[0], out var minLength))
            {
                if (int.TryParse(propertyType.Split(',')[1], out var maxLength))
                {
                    propertyType = $"string({minLength},{maxLength})";
                }
            }
        }

        var typeName = Regex.Match(propertyType, @".*?(?=\(|$)").Value?.Trim();
        var typeParamsValue = Regex.Match(propertyType, @"(?<=\().*?(?=\))").Value?.Trim();
        var typeParams = !string.IsNullOrWhiteSpace(typeParamsValue) ? typeParamsValue.Split(',') : [];

        if (typeParams.Length > 0 && (propertyType[^1] == '?' || propertyType[^1] == '!'))
        {
            typeName += propertyType[^1];
        }

        var propertyTypeBuilder = PropertyTypeBuilders.FirstOrDefault(t => t.TypeAliasNames.Any(n => n.Equals(typeName, StringComparison.OrdinalIgnoreCase)));
        if (propertyTypeBuilder != null)
        {
            propertyTypeBuilder.Build(property, typeName, typeParams);
        }
        else if (!EnumTypeBuilder.Build(property, typeName))
        {
            if (!EntityTypeBuilder.Build(property, typeName))
            {
                throw new CommandException(command, $"未知的属性类型: {typeName}");
            }
        }
    }

    public bool CanExecute(string command)
    {
        return !string.IsNullOrWhiteSpace(command);
    }

    public void Execute(string command, CommandContext context)
    {
        if (context.CurrentEntity == null)
        {
            throw new CommandException(command, "请先选择一个实体");
        }

        CreateEntityProperty(command, context.CurrentEntity);
    }
}
